import cv2
import numpy as np


def laplacian_sharpening(img_stream):
    # 读取图像
    image = cv2.imdecode(np.frombuffer(img_stream.read(), np.uint8), cv2.IMREAD_COLOR)

    # 获取图像的高度和宽度
    height, width, channels = image.shape

    # 定义锐化卷积核
    kernel = np.array([[-1, -1, -1], [-1, 9.42, -1], [-1, -1, -1]])

    # 获取卷积核的大小
    kernel_height, kernel_width = kernel.shape
    pad_height = kernel_height // 2
    pad_width = kernel_width // 2

    # 对图像进行填充
    padded_image = np.pad(
        image,
        ((pad_height, pad_height), (pad_width, pad_width), (0, 0)),
        mode="constant",
    )

    # 创建一个空的输出图像
    sharpened_image = np.zeros_like(image)

    # 遍历图像的每个像素
    for y in range(height):
        for x in range(width):
            # 应用卷积核
            for c in range(channels):  # 对每个颜色通道
                sharpened_value = 0
                for ky in range(kernel_height):
                    for kx in range(kernel_width):
                        # 计算对应的像素值
                        pixel_value = padded_image[y + ky, x + kx, c]
                        sharpened_value += kernel[ky, kx] * pixel_value

                # 赋值给输出图像
                sharpened_image[y, x, c] = np.clip(
                    sharpened_value, 0, 255
                )  # 限制像素值在 0 到 255 之间

    # 转换为 8 位无符号整型
    sharpened_image = sharpened_image.astype(np.uint8)

    _, img_encoded = cv2.imencode(".png", sharpened_image)
    return img_encoded.tobytes()


def sobel_edge_detection(img_stream):
    # 读取图像
    image = np.frombuffer(img_stream.read(), np.uint8)
    image = cv2.imdecode(image, cv2.IMREAD_GRAYSCALE)

    # 定义 Sobel 算子
    sobel_x_kernel = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    sobel_y_kernel = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])

    # 获取图像的高度和宽度
    height, width = image.shape

    # 创建空的边缘检测结果数组
    sobel_x = np.zeros_like(image, dtype=np.float32)
    sobel_y = np.zeros_like(image, dtype=np.float32)

    # 对图像进行边缘检测
    for i in range(1, height - 1):
        for j in range(1, width - 1):
            # 计算 X 方向的梯度
            gx = np.sum(sobel_x_kernel * image[i - 1 : i + 2, j - 1 : j + 2])
            sobel_x[i, j] = gx

            # 计算 Y 方向的梯度
            gy = np.sum(sobel_y_kernel * image[i - 1 : i + 2, j - 1 : j + 2])
            sobel_y[i, j] = gy

    # 组合 X 和 Y 方向的结果
    sobel_combined = np.sqrt(sobel_x**2 + sobel_y**2)

    # 将结果转换为可视化的 8 位图像
    sobel_combined = np.uint8(np.clip(sobel_combined, 0, 255))

    _, img_encoded = cv2.imencode(".png", sobel_combined)
    return img_encoded.tobytes()


# 组合锐化函数
def combine_sharpening(img_stream):
    # 读取图像
    image = np.frombuffer(img_stream.read(), np.uint8)
    image = cv2.imdecode(image, cv2.IMREAD_COLOR).astype(np.float32)
    enhanced_contrast_image = enhance_contrast(image, 1.8)
    enhanced_brightness_image = enhance_brightness(enhanced_contrast_image, 1.3)
    sharpened_image = sharpen_image(enhanced_brightness_image)
    _, img_encoded = cv2.imencode(".png", sharpened_image)
    return img_encoded.tobytes()


def enhance_contrast(image, factor=1.8):
    """
    增强图像对比度
    参数：
        image: 输入的图像 (numpy array)
        factor: 对比度增强系数
    返回：
        对比度增强后的图像
    """
    mean = np.mean(image, axis=(0, 1))
    enhanced = (image - mean) * factor + mean
    return np.clip(enhanced, 0, 255).astype(np.uint8)


def enhance_brightness(image, factor=1.3):
    """
    增强图像亮度
    参数：
        image: 输入的图像 (numpy array)
        factor: 亮度增强系数
    返回：
        亮度增强后的图像
    """
    enhanced = image * factor
    return np.clip(enhanced, 0, 255).astype(np.uint8)


def sharpen_image(image):
    """
    对图像进行锐化处理
    参数：
        image: 输入的图像 (numpy array)
    返回：
        锐化后的图像
    """
    kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
    sharpened_image = np.zeros_like(image)
    kernel_height, kernel_width = kernel.shape
    pad_height = kernel_height // 2
    pad_width = kernel_width // 2
    padded_image = np.pad(
        image,
        ((pad_height, pad_height), (pad_width, pad_width), (0, 0)),
        mode="constant",
    )
    height, width, channels = image.shape
    for y in range(height):
        for x in range(width):
            for c in range(channels):
                sharpened_value = 0
                for ky in range(kernel_height):
                    for kx in range(kernel_width):
                        pixel_value = padded_image[y + ky, x + kx, c]
                        sharpened_value += kernel[ky, kx] * pixel_value
                sharpened_image[y, x, c] = np.clip(sharpened_value, 0, 255)
    return sharpened_image.astype(np.uint8)


if __name__ == "__main__":
    # 显示拉普拉斯锐化后的图像
    laplacian_image = laplacian_sharpening("../test1_3.jpg")
    cv2.imshow("Laplacian Sharpening", laplacian_image)

    # 显示 Sobel 边缘检测后的图像
    sobel_image = sobel_edge_detection("../test1_3.jpg")
    cv2.imshow("Sobel Edge Detection", sobel_image)

    # 显示组合锐化后的图像
    combined_sharpened_image = combine_sharpening("../test1_3.jpg")
    cv2.imshow("Combined Sharpening", combined_sharpened_image)

    cv2.waitKey(0)
    cv2.destroyAllWindows()
